#ifndef _STATIC_STACK_H_
#define _STATIC_STACK_H_

#include "Stack.h"
#include "Exception.h"

namespace MySTL
{

template < typename T, int N>
class StaticStack : public Stack<T>
{
public:
	StaticStack();
	~StaticStack();

	bool push(const T& value);
	T pop();
	T& top();
	const T& top() const;
	void clear();
	int length() const;
	int capacity() const;

protected:
	T m_array[N];
	int m_length;
};

template < typename T, int N>
StaticStack<T, N>::StaticStack()
{
	m_length = 0;
}

template < typename T, int N>
StaticStack<T, N>::~StaticStack()
{
	clear();
}

template < typename T, int N>
bool StaticStack<T, N>::push(const T& value)
{
	bool ret = (0 <= m_length) && (m_length < N);

	if (ret)
	{
		m_array[m_length++] = value;
	}

	return ret;
}

template < typename T, int N>
T StaticStack<T, N>::pop()
{
	if (m_length <= 0)
	{
		THROW_EXCEPTION(InvalidOperationException, "Invalid operate in T StaticStack<T, N>::pop()");
	}

	--m_length;

	return m_array[m_length];
}

template < typename T, int N>
T& StaticStack<T, N>::top()
{
	if (m_length <= 0)
	{
		THROW_EXCEPTION(InvalidOperationException, "Invalid operate in T& StaticStack<T, N>::top()");
	}

	return m_array[m_length - 1];
}

template < typename T, int N>
const T& StaticStack<T, N>::top() const
{
	return const_cast<StaticStack<T, N>*>(this)->top();
}

template < typename T, int N>
void StaticStack<T, N>::clear()
{
	m_length = 0;
}

template < typename T, int N>
int StaticStack<T, N>::length() const
{
	return m_length;
}

template < typename T, int N>
int StaticStack<T, N>::capacity() const
{
	return N;
}

}

#endif